package com.zb.nio.filelock;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class FileLockDemo {
    public static void main(String[] args) throws IOException {
        String input = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss")) + " 测试\n";
        System.out.println("输入：" + input);

        // 创建缓冲区，并存入数据
        ByteBuffer buf = ByteBuffer.wrap(input.getBytes());
        // 文件路径
        String filePathStr = "file/05.txt";
        Path path = Paths.get(filePathStr);
        // 文件通道
        FileChannel fc = FileChannel.open(path, StandardOpenOption.APPEND);
        // position位置
        if(fc.size()!=0){
            fc.position(fc.size() - 1);
        }
        // 文件锁
        // 1、阻塞模式；默认为独占锁
        FileLock lock = fc.lock();
        // 2、阻塞模式；共享锁；只能读，不能写；写时会抛异常
        // FileLock lock = fc.lock(0,Long.MAX_VALUE,true);
        // 3、非阻塞模式；默认为独占锁；获取不到锁时，返回null，不阻塞
        // FileLock lock = fc.tryLock();
        // 4、非阻塞模式；共享锁；只能读，不能写；写时会抛异常
        // FileLock lock = fc.tryLock(0, Long.MAX_VALUE, true);

        System.out.println("是否为共享锁：" + lock.isShared());

        // 把buf中的数据写入文件通道
        fc.write(buf);
        // 关闭
        fc.close();
        System.out.println("写操作完成！");

        // 读取数据
        System.out.println("=========流读取==========");
        readFileByStream(filePathStr);
        System.out.println("=========通道读取==========");
        readFileByChannel(filePathStr);
    }

    /**
     * 流读取
     * @param filePathStr
     * @throws IOException
     */
    private static void readFileByStream(String filePathStr) throws IOException {
        FileReader fr = new FileReader(filePathStr);
        BufferedReader br = new BufferedReader(fr);
        String line = "";
        while((line = br.readLine()) !=null){
            System.out.println(line);
        }
        br.close();
    }

    /**
     * 通道读取
     * @param filePathStr
     * @throws IOException
     */
    private static void readFileByChannel(String filePathStr) throws IOException {
        FileInputStream fis = new FileInputStream(filePathStr);
        FileChannel fc = fis.getChannel();
        ByteBuffer buf = ByteBuffer.allocate(1024);
        int length = 0;
        while((length = fc.read(buf)) > 0 ){
            // buf.flip();
            System.out.println(new String(buf.array(),0,length));
            buf.clear();
        }
        fc.close();
    }
}
